import os
import sys
from typing import Any, Optional
import pathlib

import PySide6.QtCore
import PySide6.QtGui
import PySide6.QtWidgets
from PySide6.QtCore import QDir, QStandardPaths, Qt
from PySide6.QtGui import QAction, QColor, QIcon
from PySide6.QtMultimedia import QAudioOutput, QMediaFormat, QMediaPlayer
from PySide6.QtMultimediaWidgets import QVideoWidget
from PySide6.QtWidgets import (QMessageBox, QDialog, QFileDialog, QLabel, QLineEdit, QMenu,
                               QMenuBar, QPushButton, QSlider, QStyle, QCheckBox,
                               QToolBar, QVBoxLayout, QWidget)

from . import images_rc
from .utils import R
from .m3u8_downloader import M3U8Downloader

AVI = "video/x-msvideo"
MP4 = "video/mp4"


def get_mime_types():
    result = []
    for f in QMediaFormat().supportedFileFormats(QMediaFormat.Decode):
        mime_type = QMediaFormat(f).mimeType()
        result.append(mime_type.name())
    return result


class PlayerWidget(QWidget):
    def __init__(self, parent: Optional[PySide6.QtWidgets.QWidget] = None) -> None:
        super().__init__(parent)

        self._parent = parent
        self.resize(800, 600)

        self._playlist = []
        self._playlist_index = -1
        self._audio_output = QAudioOutput()
        self._player = QMediaPlayer()
        self._player.setAudioOutput(self._audio_output)

        self._player.errorOccurred.connect(self._player_error)
        self._player.positionChanged.connect(self.Player_PositionChanged)
        self._player.mediaStatusChanged.connect(self.Player_MediaStatusChanged)

        self._volume_slider = QSlider()
        self._volume_slider.setOrientation(Qt.Horizontal)
        self._volume_slider.setMinimum(0)
        self._volume_slider.setMaximum(100)
        self._volume_slider.setFixedWidth(100)
        self._volume_slider.setValue(self._audio_output.volume() * 100)
        self._volume_slider.setTickInterval(10)
        self._volume_slider.setToolTip("Volume")
        self._volume_slider.valueChanged.connect(self.SetVolume)

        self._time_slider = QSlider()
        self._time_slider.setOrientation(Qt.Horizontal)
        self._time_slider.setMinimum(0)
        self._time_slider.setValue(0)
        self._time_slider.sliderPressed.connect(self._player.pause)
        self._time_slider.sliderMoved.connect(self.Time_SliderMoved)
        self._time_slider.sliderReleased.connect(self._player.play)

        self._check_loop = QCheckBox('Loop', self)
        self._check_loop.setChecked(False)
        self._check_loop.stateChanged.connect(self.Loop_StateChanged)

        self._label_url = QLabel("  Url: ", self)
        self._text_url = QLineEdit(self)
        self._button_download = QPushButton(text="Download", parent=self)
        self._button_download.clicked.connect(self.Download)

        self._video_widget = QVideoWidget()
        self._player.playbackStateChanged.connect(self.UpdateButtons)
        self._player.setVideoOutput(self._video_widget)

        self._toolbar = QToolBar(self)
        self._toolbar.setFixedHeight(30)

        layout = QVBoxLayout()
        layout.addWidget(self._toolbar)
        layout.addWidget(self._video_widget)
        layout.addWidget(self._time_slider)
        self.setLayout(layout)

        self.InitActions()
        self.InitToolbar()

        self.UpdateButtons(self._player.playbackState())
        self._mime_types = []

    def Loop_StateChanged(self):
        if self._check_loop.isChecked() and self._player.mediaStatus() == QMediaPlayer.EndOfMedia:
            self.Next()


    def Player_PositionChanged(self, num):
        self._time_slider.setMaximum(self._player.duration())
        self._time_slider.setValue(num)

    def Player_MediaStatusChanged(self, state):
        if state == QMediaPlayer.EndOfMedia and self._check_loop.isChecked():
            self.Next()

    def Time_SliderMoved(self, num):
        self._player.setPosition(num)

    def Download(self):
        url = self._text_url.text().strip()
        if url.endswith(".m3u8"):
            m = M3U8Downloader()
            success = m.download_m3u8_to_video(url)
            QMessageBox.information(self, "下载完成", "下载成功!" if success else "下载失败!")
            return

        path = os.path.join(os.path.dirname(__file__), "run_you_get.py")
        cmd = f"python {path} {url}"
        os.system(cmd)

    def SetVolume(self):
        v = self._volume_slider.value() / 100.0
        self._audio_output.setVolume(v)

    def InitActions(self):
        self._open_action = QAction(
            QIcon(":images/open_file.gif"),
            "&Open",
            self,
            triggered=self.Open,
            shortcut="Ctrl+O",
        )

        style = self.style()
        icon = QIcon.fromTheme(
            "media-playback-start.png", style.standardIcon(QStyle.SP_MediaPlay)
        )
        self._play_action = QAction(
            icon, "&Play", self, triggered=self._player.play, shortcut="Ctrl+P"
        )

        icon = QIcon.fromTheme(
            "media-skip-backwoard-symbolic.svg",
            style.standardIcon(QStyle.SP_MediaSkipBackward),
        )
        self._previous_action = QAction(
            icon, "P&revious", self, triggered=self.Previous, shortcut="Ctrl+R"
        )

        icon = QIcon.fromTheme(
            "media-playback-pause.png", style.standardIcon(QStyle.SP_MediaPause)
        )
        self._pause_action = QAction(
            icon, "P&ause", self, triggered=self._player.pause, shortcut="Ctrl+A"
        )

        icon = QIcon.fromTheme(
            "media-skip-forward-symbolic.svg",
            style.standardIcon(QStyle.SP_MediaSkipForward),
        )
        self._next_action = QAction(
            icon, "&Next", self, triggered=self.Next, shortcut="Ctrl+N"
        )

        icon = QIcon.fromTheme(
            "media-playback-stop.png", style.standardIcon(QStyle.SP_MediaStop)
        )
        self._stop_action = QAction(
            icon, "&Stop", self, triggered=self.EnsureStopped, shortcut="Ctrl+S"
        )

        self.PlayActions = (
            self._open_action,
            self._play_action,
            self._previous_action,
            self._pause_action,
            self._next_action,
            self._stop_action,
        )

    def InitToolbar(self):
        R.AddActions(self._toolbar, self.PlayActions)
        self._toolbar.addWidget(self._volume_slider)
        self._toolbar.addWidget(self._check_loop)
        self._toolbar.addWidget(self._label_url)
        self._toolbar.addWidget(self._text_url)
        self._toolbar.addWidget(self._button_download)

    def closeEvent(self, event: PySide6.QtGui.QCloseEvent) -> None:
        self.EnsureStopped()
        event.accept()

    def _player_error(self, error, error_stirng):
        print(error_stirng, file=sys.stderr)

    def Open(self):
        self.EnsureStopped()
        dlg = QFileDialog(self)
        if not self._mime_types:
            self._mime_types = get_mime_types()
            if MP4 not in self._mime_types:
                self._mime_types.append(MP4)
        dlg.setMimeTypeFilters(self._mime_types)
        dlg.selectMimeTypeFilter(MP4)
        location = QStandardPaths.writableLocation(QStandardPaths.MoviesLocation)
        dlg.setDirectory(location)
        if dlg.exec() == QDialog.Accepted:
            url = dlg.selectedUrls()[0]
            # print(url)
            self._playlist.append(url)
            self._playlist_index += 1
            self._player.setSource(url)
            self._player.play()

    def Previous(self):
        if self._playlist_index > 0:
            self._playlist_index -= 1
        else:
            self._playlist_index = len(self._playlist) - 1
        self._player.setSource(self._playlist[self._playlist_index])
        self._player.play()

    def Next(self):
        if self._playlist_index < len(self._playlist) - 1:
            self._playlist_index += 1
        else:
            self._playlist_index = 0
        self._player.setSource(self._playlist[self._playlist_index])
        self._player.play()

    def UpdateButtons(self, state):
        count = len(self._playlist)
        self._play_action.setEnabled(count > 0 and state != QMediaPlayer.PlayingState)
        self._pause_action.setEnabled(state == QMediaPlayer.PlayingState)
        self._stop_action.setEnabled(state != QMediaPlayer.StoppedState)

    def EnsureStopped(self):
        if self._player.playbackState() != QMediaPlayer.StoppedState:
            self._player.stop()
